package com.boot2.core.web;

import com.boot2.core.JpaPageRequest;
import com.boot2.core.constant.CoreConstant;
import com.boot2.core.dao.PageInfo;
import com.boot2.core.dao.jpa.JpaDynamicSearchHolder;
import com.boot2.core.dao.mybatis.pagehelper.HlPageHelper;
import com.boot2.core.dict.ErrorCode;
import com.boot2.core.exception.BusinessException;
import com.boot2.core.model.vo.Result;
import com.boot2.core.service.AopService;
import com.boot2.core.service.SysExceptionService;
import com.boot2.core.utils.EnvironmentUtil;
import com.boot2.core.utils.JwtUtil;
import com.boot2.core.utils.ResultBuilder;
import com.boot2.core.utils.ServletUtil;
import com.boot2.core.utils.StringUtils;
import com.google.zxing.BarcodeFormat;
import com.google.zxing.WriterException;
import com.google.zxing.client.j2se.MatrixToImageWriter;
import com.google.zxing.common.BitMatrix;
import com.google.zxing.qrcode.QRCodeWriter;
import lombok.extern.apachecommons.CommonsLog;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.MessageSource;
import org.springframework.context.i18n.LocaleContextHolder;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.ui.Model;
import org.springframework.web.bind.WebDataBinder;
import org.springframework.web.bind.annotation.InitBinder;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.servlet.mvc.support.RedirectAttributes;
import org.thymeleaf.TemplateEngine;

import javax.servlet.ServletContext;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.util.Date;
import java.util.HashMap;
import java.util.Locale;
import java.util.Map;

/**
 * @author zhangweilin
 * @ClassName: BaseController
 * @description: controller基类
 * @date 2017年12月15日 下午5:33:06
 */
@CommonsLog
public class BaseController {

    @Autowired
    AopService aopService;
    @Autowired(required = false)
    private SysExceptionService sysExceptionService;
    @Autowired
    private MessageSource messageSource;

    @Autowired
    TemplateEngine templateEngine;

    @Autowired(required = false)
    protected MyRestTemplate restTemplate;

    protected void setCustomContext(Model model, HttpServletRequest request, HttpServletResponse response, PageInfo<?> pageInfo) {
        String fullUrl = ServletUtil.getFullUrl();
        addAttribute("fullUrl", fullUrl);
    }

    /**
     * 在拦截器后调用,经实验，BindingResult bindingResult不能放在此方法中处理
     *
     * @param model
     * @param request
     * @param response
     */
    @ModelAttribute
    // 此标签可以在所有action方法执行前被执行，
    protected void setReqAndResp(Model model, HttpServletRequest request, HttpServletResponse response, RedirectAttributes redirectAttributes, PageInfo<?> pageInfo) {
        RequestContext.get().setModel(model);
        RequestContext.get().setRedirectAttributes(redirectAttributes);
        if (pageInfo.getPageNo() < 1) {
            pageInfo.setPageNo(1); // 最低只能到第1页
        }
        Integer pageSize = EnvironmentUtil.get("sys.page.maxPageSize", Integer.class);
        pageSize = pageSize != null ? pageSize : 200;
        if (pageInfo.getPageSize() > pageSize) { // 最多一次性查询200条
            pageInfo.setPageSize(pageSize);
        }
        RequestContext.get().setPageInfo(pageInfo);
        setCustomContext(model, request, response, pageInfo);
    }

    /**
     * mybatis分页
     */
    protected void startPage() {
        HlPageHelper.startPage();
    }

    /**
     * mybatis分页
     *
     * @param pageNo
     */
    protected void startPage(Integer pageNo) {
        HlPageHelper.startPage(pageNo);
    }

    /**
     * mybatis分页
     *
     * @param pageNo
     * @param pageSize
     */
    protected void startPage(Integer pageNo, Integer pageSize) {
        HlPageHelper.startPage(pageNo, pageSize);
    }

    protected int pageNo() {
        return pageInfo().getPageNo();
    }

    protected int pageSize() {
        return pageInfo().getPageSize();
    }

    /**
     * jpa的分页
     *
     * @return
     */
    protected PageRequest jpaPageRequest() {
        return JpaPageRequest.of();
    }

    /**
     * jpa分页
     *
     * @param pageNo
     * @return
     */
    public PageRequest jpaPageRequest(int pageNo) {
        return JpaPageRequest.of(pageNo);
    }

    /**
     * jpa的分页
     *
     * @param pageNo
     * @param pageSize
     * @return
     */
    protected PageRequest jpaPageRequest(Integer pageNo, Integer pageSize) {
        return JpaPageRequest.of(pageNo, pageSize);
    }

    /**
     * jpa的分页
     *
     * @param direction
     * @param properties
     * @return
     */
    public PageRequest jpaPageRequest(Sort.Direction direction, String... properties) {
        return JpaPageRequest.of(direction, properties);
    }

    /**
     * jpa的分页
     *
     * @param pageNo
     * @param pageSize
     * @param direction
     * @param properties
     * @return
     */
    public PageRequest jpaPageRequest(int pageNo, int pageSize, Sort.Direction direction, String... properties) {
        return JpaPageRequest.of(pageNo, pageSize, direction, properties);
    }

    /**
     * jpa的分页
     *
     * @param sort
     * @return
     */
    public PageRequest jpaPageRequest(Sort sort) {
        return JpaPageRequest.of(sort);
    }

    /**
     * jpa的分页
     *
     * @param pageNo
     * @param pageSize
     * @param sort
     * @return
     */
    public PageRequest jpaPageRequest(int pageNo, int pageSize, Sort sort) {
        return JpaPageRequest.of(pageNo, pageSize, sort);
    }

//    /**
//     * 参数为空异常处理
//     *
//     * @param exception
//     * @return
//     */
//    @ExceptionHandler(ErrorCodeException.class)
//    @ResponseBody
//    public Result<String> exceptionErrorCode(ErrorCodeException exception) throws Exception {
////        Response<String> result = resultError(exception.getErrorCode(), exception.getErrorMessage());
//        sendExceptionInfo(exception);
////        return result;
//
//        // 如果是ajax请求,返回json
//        if (ServletUtil.isAjaxRequest()) {
//            Result<String> result = resultError(exception.getErrorCode(), exception.getErrorMessage());
//            return result;
//            // 返回错误页面
//        } else {
//            handException(exception, true);
//            return null;
//        }
//    }
//
//    /**
//     * 参数为空异常处理
//     * pageInfo
//     *
//     * @param exception
//     * @return
//     */
//    @ExceptionHandler(TokenValidationException.class)
//    @ResponseBody
//    public Result<String> exceptionTokenValidation(TokenValidationException exception) throws Exception {
////        Response<String> result = result401(exception.getMessage());
////        sendExceptionInfo(exception);
////        return result;
//        sendExceptionInfo(exception);
//        // 如果是ajax请求,返回json
//        if (ServletUtil.isAjaxRequest()) {
//            Result<String> result = result400(exception.getMessage());
//            return result;
//            // 返回错误页面
//        } else {
//            handException(exception, true);
//            return null;
//        }
//    }
//
//    /**
//     * 未登陆异常
//     *
//     * @param exception
//     * @return
//     * @throws Exception
//     */
//    @ExceptionHandler(NotLoginedException.class)
//    @ResponseBody
//    public Result<String> exceptionNotLogined(NotLoginedException exception) throws Exception {
////        Response<String> result = result401(exception.getMessage());
////        sendExceptionInfo(exception);
////        return result;
//        sendExceptionInfo(exception);
//        // 如果是ajax请求,返回json
//        if (ServletUtil.isAjaxRequest()) {
//            Result<String> result = result401(exception.getMessage());
//            return result;
//            // 返回错误页面
//        } else {
//            handException(exception, true);
//            return null;
//        }
//    }
//
//    /**
//     * 参数为空异常处理
//     * pageInfo
//     *
//     * @param exception
//     * @return
//     */
//    @ExceptionHandler({ParamEmptyException.class})
//    @ResponseBody
//    public Result<String> exceptionParam1(Exception exception) throws Exception {
////        Response<String> result = result400(exception.getMessage());
////        sendExceptionInfo(exception);
////        return result;
//        sendExceptionInfo(exception);
//        // 如果是ajax请求,返回json
//        if (ServletUtil.isAjaxRequest()) {
//            Result<String> result = result400(exception.getMessage());
//            return result;
//            // 返回错误页面
//        } else {
//            handException(exception, true);
//            return null;
//        }
//    }
//
//    /**
//     * 参数为空异常处理
//     * pageInfo
//     *
//     * @param exception
//     * @return
//     */
//    @ExceptionHandler({MissingServletRequestParameterException.class})
//    @ResponseBody
//    public Result<String> exceptionParam2(Exception exception) throws Exception {
////        Response<String> result = result400(exception.getMessage());
////        sendExceptionInfo(exception);
////        return result;
//        sendExceptionInfo(exception);
//        // 如果是ajax请求,返回json
//        if (ServletUtil.isAjaxRequest()) {
//            Result<String> result = result500("param error");
//            return result;
//            // 返回错误页面
//        } else {
//            handException(exception, false);
//            return null;
//        }
//    }
//
//    /**
//     * 空指针异常
//     *
//     * @param exception
//     * @param request
//     * @return
//     */
//    @ExceptionHandler({NullPointerException.class})
//    @ResponseBody
//    public Result<String> exceptionNull(Exception exception) throws Exception {
////        Response<String> result = result500("空指针异常1:" + exception.getMessage());
////        sendExceptionInfo(exception);
////        return result;
//        sendExceptionInfo(exception);
//        // 如果是ajax请求,返回json
//        if (ServletUtil.isAjaxRequest()) {
//            Result<String> result = result500("null null null!!!!!!");
//            return result;
//            // 返回错误页面
//        } else {
//            handException(exception, false);
//            return null;
//        }
//    }
//
//    @ExceptionHandler({MethodArgumentTypeMismatchException.class})
//    @ResponseBody
//    public Result<String> exceptionMethodArgumentTypeMismatchException(Exception exception) throws Exception {
////        Response<String> result = result500("非法参数");
////        sendExceptionInfo(exception);
////        return result;
//
//        sendExceptionInfo(exception);
//        // 如果是ajax请求,返回json
//        if (ServletUtil.isAjaxRequest()) {
//            Result<String> result = result500("param error");
//            return result;
//            // 返回错误页面
//        } else {
//            handException(exception, false);
//            return null;
//        }
//    }
//
//    /**
//     * @param exception
//     * @param request
//     * @return
//     * @ExceptionHandler在此处定义全局处理，通过@ExceptionHandler的value属性可过滤拦截的条件， 再此我们可以看出我们拦截所有的Exception
//     */
//    @ExceptionHandler(value = Exception.class)
//    @ResponseBody
//    protected Result<String> exception(Exception exception) throws Exception {
////        Response<String> result = result500(exception.getMessage());
////        sendExceptionInfo(exception);
////        return result;
//
////        exception.printStackTrace();
//        sendExceptionInfo(exception);
//        // 如果是ajax请求,返回json
//        if (ServletUtil.isAjaxRequest()) {
//            Result<String> result = result500("Server Error");
//            return result;
//            // 返回错误页面
//        } else {
//            handException(exception, false);
//            return null;
//        }
//    }
//
//    /**
//     * @param exception
//     * @param request
//     * @return
//     * @ExceptionHandler在此处定义全局处理，通过@ExceptionHandler的value属性可过滤拦截的条件， 再此我们可以看出我们拦截所有的Exception
//     */
//    @ExceptionHandler(value = IllegalArgumentException.class)
//    @ResponseBody
//    protected Result<String> exceptionIllegalArgumentException(Exception exception) throws Exception {
////        Response<String> result = result500(exception.getMessage());
////        sendExceptionInfo(exception);
////        return result;
//
////        exception.printStackTrace();
//        sendExceptionInfo(exception);
//        StackTraceElement[] stackTrace = exception.getStackTrace();
//        String className = stackTrace[1].getClassName();
//        String errorMessage = exception.getMessage();
//        //如果不是自定义的断言抛的，则不往外提示
//        boolean isAssert = true;
//        if (!className.endsWith("HlAssert")) {
//            errorMessage = "Server Error";
//            isAssert = false;
//        }
//
//        // 如果是ajax请求,返回json
//        if (ServletUtil.isAjaxRequest()) {
//            Result<String> result = null;
//            //正常的业务提示，走400
//            if (isAssert) {
////                result = result400(errorMessage);
//                result = result600(errorMessage);
//                //服务端内部异常 走500
//            } else {
//                result = result500(errorMessage);
//            }
//            return result;
//            // 返回错误页面
//        } else {
//            handException(exception, isAssert);
//            return null;
//        }
//    }
//
//    private void handException(Exception exception, boolean isAssert) throws Exception {
//        //如果是由feign调用的，则直接抛到上游
//        HttpServletRequest request = RequestContext.getRequest();
//        String feignHeader = request.getHeader(FeignBasicAuthRequestInterceptor.headerKey);
//        if (StringUtils.isNotEmpty(feignHeader)) {
//            throw exception;
//        }
//
//        Model model = model();
//        //系统内部异常，异常信息，不展现到前端
//        if (!isAssert) {
//            model.addAttribute("errorMessage", "server error，please contact your system admin or technical support group for further assistance,email: zwllxs@qq.com/18721279166，thank you");
//            // 以下为兼容内置的错误视图，否则会报如EL1008E: Property or field 'timestamp' cannot be found on
//            // object of type 'java.util.HashMap' 这样的异常
//            model.addAttribute("timestamp", new Date());
//            model.addAttribute("error", HttpStatus.INTERNAL_SERVER_ERROR.name());
//            model.addAttribute("status", HttpStatus.INTERNAL_SERVER_ERROR.getReasonPhrase());
//        } else {
//            //业务异常提示，异常信息，原样展现到前端
//            model.addAttribute(CoreConstant.operationToastError, exception.getMessage());
//        }
//        log.error("系统异常," + exception.getMessage(), exception);
////        request().getRequestDispatcher("500").forward(request(), response());
////        return "500";
//        String content = null;
//        try {
//            content = TemplatesUtil.createTemplates(null, "500", templateEngine);
//        } catch (Exception e) {
//            e.printStackTrace();
//            log.error("异常处理失败", e);
//            model.addAttribute("title", "server error detail (if possiable,it's better to config a 500 page)");
//            content = JSON.toJSONString(model);
//        }
//        PrintWriter writer = response().getWriter();
//        writer.write(content);
//        writer.flush();
//        writer.close();
//    }
//
//    /**
//     * 发送异常处理
//     *
//     * @param exception
//     * @param request
//     * @return
//     */
//    private boolean sendExceptionInfo(Exception exception) {
//        String errorMessage = exception.getMessage();
//        //此异常没找到好办法，无须监控
//        if (StringUtils.isNotEmpty(errorMessage)) {
//            if (errorMessage.contains("java.io.IOException: Broken pipe")) {
//                return true;
//            }
//        }
//        Map<String, String>[] requestInfoMap = ServletUtil.getClientInfoStat(request());
//        sendExceptionInfo(requestInfoMap, exception);
//        return false;
//    }
//
//    /**
//     * 单应用系统中在本controller中直接调用，如果是分布式系统且引用本core，则从网关调过来的controller，
//     * 是没有Service的，
//     * 故不能直接调用本方法，介时的controller，继承此方法即可处理全部异常
//     *
//     * @param requestInfoMap
//     * @param ex
//     */
//    public void sendExceptionInfo(Map<String, String>[] requestInfoMap, Exception ex) {
//        Boolean isAssert = false;
//        if (ex instanceof IllegalArgumentException) {
//            StackTraceElement[] stackTrace = ex.getStackTrace();
//            String className = stackTrace[1].getClassName();
//            isAssert = className.endsWith("HlAssert");
////            if (className.endsWith("Assert")) {
////                isAssert = true;
////            }
//        }
//
//        //在aop的环绕后面写日志时，如果用异常机制弹出了提示或抛出了异常，会导入日志执行不到，即环绕后面执行不到，此情况会执行到此处，则此处可以把日志入库
//        HttpServletRequest request = request();
//        Object proceedingJoinPoint = request.getAttribute(AbstractAop.methodJoinPointKey);
//        AbstractLog abstractLog = (AbstractLog) request.getAttribute(CoreConstant.userLog);
//        if (null != abstractLog) {
//            abstractLog.setExceptionMessage(ex.getMessage());
//            request.setAttribute(CoreConstant.userLog, abstractLog);
//            try {
//                aopService.handLog(RequestContext.getHandler(), request, (ProceedingJoinPoint) proceedingJoinPoint);
//            } catch (Exception e) {
//                e.printStackTrace();
//                log.error("日志入库失败", e);
//            }
//        }
//
//        //如果是断言，是业务逻辑判断，就不用打印异常堆栈了
//        if (!isAssert) {
//            ex.printStackTrace();
//            if (null != sysExceptionService) {
//                sysExceptionService.sendExceptionInfo(requestInfoMap, proceedingJoinPoint, RequestContext.getHandler(), ex);
//            }
//        }
//    }

    protected Long getJwtUserId() {
        String userId = getHeader(JwtUtil.USER_ID);
        if (null == userId) {
            return null;
        }
        return Long.parseLong(userId);
    }

    /**
     * 通过@InitBinder注解定制WebDataBinder
     *
     * @param webDataBinder
     */
    @InitBinder
    protected void initBinder(WebDataBinder webDataBinder) {
        // 此处演示忽略request参数的id
        // webDataBinder.setDisallowedFields("id");//此不会将id绑定到任何对象上去，可以为一些系统级的属性，如创建时间之类的进行屏蔽
        // 以下屏蔽受保护的系统字段
        webDataBinder.setDisallowedFields("ids");
        webDataBinder.setDisallowedFields("createTime");
        webDataBinder.setDisallowedFields("updateTime");
        webDataBinder.setDisallowedFields("createrName");
        webDataBinder.setDisallowedFields("updaterName");
        webDataBinder.setDisallowedFields("isDeleted");

        //此处为 接收页面的字符串到对象，另一处的序列化，即java对象到json, 在FastJsonConfigs中
        webDataBinder.registerCustomEditor(Date.class, DateEditor.getInstance());
//        webDataBinder.registerCustomEditor(Long.class, new DecipherLongIdEditor());

        customInitBinder(webDataBinder);
    }

    /**
     * 在业务代码中要额外绑定的,比如  webDataBinder.setAutoGrowCollectionLimit(2048);
     *
     * @param webDataBinder
     */
    protected void customInitBinder(WebDataBinder webDataBinder) {

    }

    protected void addAttribute(String key, Object obj) {
        RequestContext.getModel().addAttribute(key, obj);
    }

    /**
     * 添加错误消息
     *
     * @param obj
     */
    protected void addErrorMessage(Object obj) {
        addFlashAttribute(CoreConstant.operationToastError, obj);
        addAttribute(CoreConstant.operationToastError, obj);
    }

    /**
     * 添加成功提示消息
     *
     * @param obj
     */
    protected void addOkMessage(Object obj) {
        addFlashAttribute(CoreConstant.operationToastOk, obj);
        addAttribute(CoreConstant.operationToastOk, obj);
    }


    protected void addFlashAttribute(String key, Object obj) {
        RequestContext.getRedirectAttributes().addFlashAttribute(key, obj);
    }

    protected HttpSession session() {
        return RequestContext.getSession();
    }

    protected ServletContext servletContext() {
        return session().getServletContext();
    }

    protected HttpServletRequest request() {
        return RequestContext.getRequest();
    }

    protected String getHeader(String name) {
        return request().getHeader(name);
    }

    protected HttpServletResponse response() {
        return RequestContext.getResponse();
    }

    protected Map<String, Cookie> cookies() {
        return RequestContext.getCookies();
    }

    protected Model model() {
        return RequestContext.getModel();
    }

    protected RedirectAttributes redirectAttributes() {
        return RequestContext.getRedirectAttributes();
    }

    protected <T> PageInfo<T> pageInfo() {
        return RequestContext.getPageInfo();
    }

    protected Pageable pageable() {
        return RequestContext.getPageable();
    }

    /**
     * 响应错误
     *
     * @param errorCode
     * @return
     */
    protected <T> Result<T> resultError(String errorCode) {
        return ResultBuilder.buildResult(errorCode);
    }

    /**
     * 响应错误
     *
     * @param errorCode
     * @return
     */
    protected <T> Result<T> resultError(Integer errorCode) {
        return ResultBuilder.buildResult(errorCode + "");
    }

    /**
     * 响应错误
     *
     * @param errorCode
     * @param errorMessage
     * @return
     */
    protected <T> Result<T> resultError(String errorCode, T errorMessage) {
        return ResultBuilder.buildResult(errorCode, errorMessage);
    }

    /**
     * 响应错误
     *
     * @param errorCode
     * @param errorMessage
     * @return
     */
    protected <T> Result<T> resultError(String errorCode, T result, Object errorMessage) {
        return ResultBuilder.buildResult(errorCode, result, errorMessage);
    }

    /**
     * 响应错误
     *
     * @param errorCode
     * @param errorMessage
     * @return
     */
    protected <T> Result<T> resultError(Integer errorCode, T errorMessage) {
        return ResultBuilder.buildResult(errorCode + "", errorMessage);
    }

    /**
     * 响应错误
     *
     * @param errorCode
     * @param errorMessage
     * @return
     */
    protected <T> Result<T> resultError(Integer errorCode, T result, String errorMessage) {
        return ResultBuilder.buildResult(errorCode + "", result, errorMessage);
    }


//    protected <T> void put(Stinrg,) {
//
//
//    }

    /**
     * 301跳转
     */
    protected Result<String> result301(String url) {
        Result<String> result = ResultBuilder.buildResult(ErrorCode.code_301);
        result.setMessage(null);
        result.setResult(url);
        return result;
    }

    /**
     * 响应接口参数错误
     */
    protected <T> Result<T> result400() {
        return ResultBuilder.buildResult(ErrorCode.code_400);
    }

    /**
     * 响应接口参数错误
     *
     * @param errorMessage
     * @return
     */
    protected <T> Result<T> result400(Object errorMessage) {
        return ResultBuilder.buildResult(ErrorCode.code_400, errorMessage);
    }

    /**
     * 响应接口参数错误
     *
     * @param errorMessage
     * @return
     */
    protected <T> Result<T> result400(T result, Object errorMessage) {
        return ResultBuilder.buildResult(ErrorCode.code_400, result, errorMessage);
    }

    /**
     * 401
     */
    protected <T> Result<T> result401() {
        return ResultBuilder.buildResult(ErrorCode.code_401);
    }

    /**
     * 401
     *
     * @param errorMessage
     * @return
     */
    protected <T> Result<T> result401(Object errorMessage) {
        return ResultBuilder.buildResult(ErrorCode.code_401, errorMessage);
    }

    /**
     * 401
     *
     * @param errorMessage
     * @return
     */
    protected <T> Result<T> result401(T result, Object errorMessage) {
        return ResultBuilder.buildResult(ErrorCode.code_401, result, errorMessage);
    }

    /**
     * 403
     */
    protected <T> Result<T> result403() {
        return ResultBuilder.buildResult(ErrorCode.code_403);
    }

    /**
     * 403
     *
     * @param errorMessage
     * @return
     */
    protected <T> Result<T> result403(Object errorMessage) {
        return ResultBuilder.buildResult(ErrorCode.code_403, errorMessage);
    }

    /**
     * 403
     *
     * @param errorMessage
     * @return
     */
    protected <T> Result<T> result403(T result, Object errorMessage) {
        return ResultBuilder.buildResult(ErrorCode.code_403, result, errorMessage);
    }

    /**
     * 响应接口不存在
     */
    protected <T> Result<T> result404() {
        return ResultBuilder.buildResult(ErrorCode.code_404);
    }

    /**
     * 响应接口不存在
     *
     * @param errorMessage
     * @return
     */
    protected <T> Result<T> result404(Object errorMessage) {
        return ResultBuilder.buildResult(ErrorCode.code_404, errorMessage);
    }

    /**
     * 响应接口不存在
     *
     * @param errorMessage
     * @return
     */
    protected <T> Result<T> result404(T result, Object errorMessage) {
        return ResultBuilder.buildResult(ErrorCode.code_404, result, errorMessage);
    }

    /**
     * 响应接口服务端错误
     */
    protected <T> Result<T> result500() {
        return ResultBuilder.buildResult(ErrorCode.code_500);
    }

    /**
     * 响应接口服务端错误
     *
     * @param errorMessage
     * @return
     */
    protected <T> Result<T> result500(Object errorMessage) {
        return ResultBuilder.buildResult(ErrorCode.code_500, errorMessage);
    }

    /**
     * 响应接口服务端错误
     *
     * @param errorMessage
     * @return
     */
    protected <T> Result<T> result500(T result, Object errorMessage) {
        return ResultBuilder.buildResult(ErrorCode.code_500, result, errorMessage);
    }

    /**
     * 接口请求正常，但是有来自接口的业务提示
     *
     * @param errorMessage
     * @return
     */
    protected <T> Result<T> error(Object errorMessage) {
        return result600(errorMessage);
    }

    /**
     * 接口请求正常，但是有来自接口的业务提示
     *
     * @param errorMessage
     * @return
     */
    protected <T> Result<T> result600(Object errorMessage) {
        return ResultBuilder.buildResult(ErrorCode.code_600, errorMessage);
    }


    /**
     * 接口请求正常，但是有来自接口的业务提示
     *
     * @param errorMessage
     * @return
     */
    protected <T> Result<T> result600(T result, Object errorMessage) {
        return ResultBuilder.buildResult(ErrorCode.code_600, result, errorMessage);
    }

    /**
     * 响应操作成功
     */
    protected <T> Result<T> resultSuccess() {
        return ResultBuilder.buildResult(ErrorCode.code_200);
    }

    /**
     * 响应操作成功
     */
    protected <T> Result<T> success() {
        return resultSuccess();
    }

    /**
     * 响应操作成功,仅针对分页结果
     */
    protected <T> Result<T> page(Object result) {
        return ResultBuilder.buildPageResult(result);
    }

    /**
     * 响应操作成功,并返回对应结果
     *
     * @param result 响应信息
     */
    protected <T> Result<T> resultSuccess(T result) {
        return ResultBuilder.buildResult(result);
    }

    /**
     * 响应操作成功,并返回对应结果
     *
     * @param result 响应信息
     */
    protected <T> Result<T> success(T result) {
        return resultSuccess(result);
    }

    /**
     * 构建结果结构为map的响应体
     *
     * @param key
     * @param t
     * @param <T>
     * @return
     */
    protected <T> Result<Map<String, T>> map(String key, T t) {
        return ResultBuilder.buildSuccessMapResponse(key, t);
    }

//    /**
//     * 构建结果结构为map的响应体
//     *
//     * @param key
//     * @param t
//     * @param <T>
//     * @return
//     */
//    protected <T> Result<Map<String, T>> mapSuccess(String key, T t) {
//        return map(key, t);
//    }

    protected String getMethod() {
        return request().getMethod();
    }

    protected Map<String, String[]> getParameters() {
        return request().getParameterMap();
    }

    protected String getParameter(String key) {
        return request().getParameter(key);
    }

    /**
     * 设置编码
     *
     * @param encoding
     */
    protected void setCharacterEncoding(String encoding) {
        response().setCharacterEncoding(encoding);
    }

    protected void setContentType(String contentType) {
        response().setContentType(contentType);
    }

    protected void setHeader(String key, String value) {
        response().setHeader(key, value);
    }

    protected void sendRedirect(String url) throws IOException {
        response().sendRedirect(url);
    }

    protected void saveMessage(String msg) {
        request().setAttribute("messages", msg);
    }

    protected void errorMessage(String msg) {
        request().setAttribute("errorMessages", msg);
    }

    protected String getCookieValue(String cookieName) {
        Cookie cookie = getCookie(cookieName);
        return cookie == null ? null : cookie.getValue();
    }

    protected Cookie getCookie(String cookieName) {
        Cookie[] cookies = request().getCookies();
        if (cookies != null) {
            for (Cookie cookie : cookies) {
                if (cookie.getName().equals(cookieName)) {
                    return cookie;
                }
            }
        }
        return null;
    }


//    protected void sendAjaxMsg(String msg, boolean isWarpScript) {
//        HttpServletResponse response = response();
//        response.setContentType(contentTypeHtmlUTF8);
//        response.setCharacterEncoding(defaultEncode);
//        try {
//            PrintWriter out = response.getWriter();
//            if (isWarpScript) {
//                out.write("<script type='text/javascript'>" + msg + "</script>");
//            } else {
//                out.write(msg);
//            }
//            out.flush();
//            out.close();
//        } catch (Exception e) {
//            e.printStackTrace();
//        }
//    }

//    protected void alert(String msg) {
//        HttpServletResponse response = response();
//        response.setContentType(contentTypeHtmlUTF8);
//        response.setCharacterEncoding(defaultEncode);
//        try {
//            PrintWriter out = response.getWriter();
//            out.write("<script type='text/javascript'>alert('" + msg + "')</script>");
//            out.flush();
//            out.close();
//        } catch (Exception e) {
//            e.printStackTrace();
//        }
//    }
//
//    /**
//     * 发送Ajax请求结果json
//     *
//     * @throws ServletException
//     * @throws IOException
//     */
//    protected void sendAjaxResultByJson(String json) {
//        HttpServletResponse response = response();
//        response.setContentType(contentTypeJsonUTF8);
//        response.setCharacterEncoding(defaultEncode);
//        try {
//            PrintWriter out = response.getWriter();
//            out.write(json);
//            out.flush();
//            out.close();
//        } catch (Exception e) {
//            e.printStackTrace();
//        }
//    }

    /**
     * 默认情况 下，健为enum
     *
     * @param enumArr
     */
    protected void addEnumAttribute(Enum[] enumArr) {
        addEnumAttribute("enum", enumArr, null);
    }

    /**
     * 默认情况 下，健为enum
     *
     * @param enumArr
     * @param keyScope
     */
    protected void addEnumAttribute(Enum[] enumArr, EnumType keyScope) {
        addEnumAttribute("enum", enumArr, keyScope);
    }

    /**
     * 将指定的枚举 ,设置到map中并传到页面上去
     *
     * @param key
     * @param enumArr
     */
    protected void addEnumAttribute(String key, Enum[] enumArr) {
        addEnumAttribute(key, enumArr, "getIndex", "getText", null);
    }

    /**
     * 将指定的枚举 ,设置到map中并传到页面上去
     *
     * @param enumArr
     * @param key
     * @param keyScope
     */
    protected void addEnumAttribute(String key, Enum[] enumArr, EnumType keyScope) {
        addEnumAttribute(key, enumArr, "getIndex", "getText", keyScope);
    }

    /**
     * 将指定的枚举 ,设置到map中并传到页面上去
     *
     * @param enumArr
     * @param keyMethod
     * @param valueMethod
     * @param keyScope
     */
    protected void addEnumAttribute(String key, Enum<?>[] enumArr, String keyMethod, String valueMethod, EnumType keyScope) {
        Map<Object, Object> enumMap = getEnumMap(enumArr, keyMethod, valueMethod, keyScope);
        addAttribute(key, enumMap);
    }

    /**
     * 获取枚举集合
     *
     * @param enumArr
     * @return
     */
    protected Map<Object, Object> getEnumMap(Enum<?>[] enumArr) {
        return getEnumMap(enumArr, "getIndex", "getText", null);
    }

    /**
     * 获取枚举集合
     *
     * @param enumArr
     * @param keyMethod
     * @param valueMethod
     * @param keyScope
     * @return
     */
    protected Map<Object, Object> getEnumMap(Enum<?>[] enumArr, String keyMethod, String valueMethod, EnumType keyScope) {
        Map<Object, Object> enumMap = new HashMap<>();
        for (Enum<?> enum0 : enumArr) {
            Class<?> clazz3 = enum0.getClass();
            try {
                Object valueKey = clazz3.getDeclaredMethod(keyMethod).invoke(enum0);
                Object valueObj = clazz3.getDeclaredMethod(valueMethod).invoke(enum0);
                String valueName = enum0.name();
                if (valueName.equals("falseValue") || valueName.equals("trueValue")) {
                    valueName = valueName.replace("Value", "");
                }

                if (null == keyScope) {
                    enumMap.put(valueName, valueObj);
                    enumMap.put(valueKey, valueObj);
                } else if (keyScope.name().equalsIgnoreCase(EnumType.enumName.name())) {
                    enumMap.put(valueName, valueObj);
                } else if (keyScope.name().equalsIgnoreCase(EnumType.enumKey.name())) {
                    enumMap.put(valueKey, valueObj);
                }
            } catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException | NoSuchMethodException | SecurityException e) {
                e.printStackTrace();
            }
        }
        return enumMap;
    }

    /**
     * 生成web版本二维码
     *
     * @param url    要生成二维码的路径
     * @param width  二维码宽度
     * @param height 二维码高度
     * @throws IOException
     */
    protected void genQRCode(String url, int width, int height) throws IOException {
        if (url != null && !"".equals(url)) {
            ServletOutputStream stream = null;
            try {
                stream = response().getOutputStream();
                QRCodeWriter writer = new QRCodeWriter();
                BitMatrix m = writer.encode(url, BarcodeFormat.QR_CODE, height, width);
                MatrixToImageWriter.writeToStream(m, "png", stream);
            } catch (WriterException e) {
                e.printStackTrace();
                log.error("生成二维码失败!");
            } finally {
                if (stream != null) {
                    stream.flush();
                    stream.close();
                }
            }
        }
    }

    /**
     * 获取登录后的跳转页
     */
    protected String getLastUrl() {
        String lastPath = (String) session().getAttribute(CoreConstant.currentFullUrlSessionKey);
        lastPath = StringUtils.isEmpty(lastPath) ? "/" : lastPath;
        return "redirect:" + lastPath;
    }

    /**
     * 纯页面跳转
     *
     * @param path1
     * @param pageFile(此处不能用page参数。因为已经被spring
     *data分页使用)
     * @return
     */
//	@GetMapping("/page_{path1}_{pageFile}")
//	protected String baseToPage(@PathVariable String path1, @PathVariable String pageFile) {
//		return path1 + "/" + pageFile;
//	}

    /**
     * 国际化
     *
     * @param messageKey
     * @return
     */
    public String getI18nMessage(String messageKey, Object[] params) {
        String message = "";
        try {
            Locale locale = LocaleContextHolder.getLocale();
            message = messageSource.getMessage(messageKey, params, locale);
        } catch (Exception e) {
            e.printStackTrace();
            throw new BusinessException("获取国际化消息失败", e);
        }
        return message;
    }

    /**
     * 设置动态条件搜索key,记录接收到的操作符，如列表页搜索时，为appDeviceSn:like,appCode:like,id:<=,createTime:between
     *
     * @param expression 形如appDeviceSn:like,appCode:like,id:<=,createTime:between的动态表达式
     */
    public void setSearchOpExpression(String expression) {
//        request().setAttribute(CoreConstant.searchOpRequestAttibuteKey, expression);
        JpaDynamicSearchHolder.set(expression);
    }

    /**
     * @author zhangweilin
     * @description: 数据库中存储的枚举值，有时是枚举的name，有时是枚举中的构造中的第一个参数发，即对应的数码key
     * @date 2018年1月13日 下午3:43:08
     */
    protected enum EnumType {
        // 枚举的name
        enumName,
        // 枚举的key,即构造中的key，
        enumKey;
    }
}
